package main

import "fmt"

//结构体的使用
//结构体是复合类型（composite types），当需要定义一个类型，它由一系列属性组成，每个属性都有自己的类型和值的时候，就应该使用结构体，它把数据聚集在一起。
//结构体也是值类型，因此可以通过 new 函数来创建。
//在一个结构体中，字段名字必须是唯一的。
//结构体的概念在软件工程上旧的术语叫 ADT（抽象数据类型：Abstract Data Type）。在 C++ 它也存在，并且名字也是 struct，在面向对象的编程语言中，
// 跟一个无方法的轻量级类一样。因为 Go 语言中没有类的概念，所以在 Go 中结构体有着更为重要的地位。

type Student struct {
	name   string
	age    int
	weight float32
	score  []int
}

//如果成员变量的类型相同的话，可以把它们写到同一行
type T struct{ num1, num2, num3 int }

func TestStruct() {
	//按照字段顺序进行初始化
	stu1 := Student{"GoLang", 24, 55.5, []int{12, 34, 56}}
	//通过 field:value 形式初始化，该方式可以自定义初始化字段的顺序
	stu2 := Student{age: 25, name: "Python", score: []int{5, 6, 7}, weight: 66.6}
	fmt.Println(stu1)
	fmt.Printf("%v\n", stu2)

	//取出值  并 修改值
	stu1.age += 1
	fmt.Println(stu1.age)
}

func TestStruct2() {
	//t、t2 通常被称做类型T的一个实例（instance）或对象（Object）

	t := new(T)    //给该结构体变量分配内存，它返回指向已分配内存的指针。变量 t是一个指向T的指针，此时结构体字段的值是它们所属类型的零值。
	fmt.Println(t) //&{0 0 0}

	var t2 T        //也会给 t2 分配内存，并零值化内存，但是这个时候t2是类型T
	fmt.Println(t2) //{0 0 0}

	var t3 *T = new(T)
	fmt.Println(t3) //&{0 0 0}
	//t与t3等价
}

type structTest struct {
	num1   int
	float1 float32
	str    string
}

func TestStruct3() {
	ms := new(structTest)
	ms.num1 = 123
	ms.float1 = 5.6
	ms.str = "string"

	fmt.Println(ms.str, ms.float1, ms.num1)
	fmt.Println(ms)
}

func main() {
	//TestStruct()
	//TestStruct2()
	TestStruct3()
}
